#pragma once

class Config {
	static json::grammar<char>::object root;

public:
	// load settings from a file
	static void Load(const char *filename);	

	static json::grammar<char>::object Get(const std::string &key) {
		return boost::any_cast<json::grammar<char>::object>(*root.find(key)->second);
	}
	
	template <class T>
	static void TryAssign(T &var, const std::string &key, json::grammar<char>::object &o);

	static json::grammar<char>::object &Root() { return root; }

	template <class T>
	static void myAssign(T &var, const json::grammar<char>::variant &v) {
		try {
			var = boost::any_cast<typename T>(*v);
		} catch(const std::exception &) {
			std::cerr << "Using default value: " << var << "\n";
		}
	}

	static void AssignArray(boost::numeric::ublas::vector<double> &dest, const json::grammar<char>::array &src) {
		dest.resize(src.size());
		for(int i = 0; i < dest.size(); i++) {
			myAssign(dest[i], src[i]);
		}
	}

	static bool Debug;					// print debugging messages

};

template <class T>
void Config::TryAssign(T &var, const std::string &key, json::grammar<char>::object &o) {
	json::grammar<char>::object::iterator it = o.find(key);
	if(it == o.end()) {
		std::cerr << "\"" << key << "\" not found in config file. Using default value: " << var << "\n";
		return;
	}
	try {
		var = boost::any_cast<typename T>(*it->second);
	} catch(const std::exception &) {
		std::cerr << "\"" << key << "\" has incorrect type. Using default value: " << var << "\n";
	}
}

